import bitPack

class Rule:
  def __init__(self):
    self.text = ""
    self.lhs = ""
    self.rhs = []
    self.tokenMap = dict()
    self.headerName = ""
  def toString(self):
    s = ""
    s += self.lhs + " -> " + " ".join(self.rhs)
    return s

class Conflict:
  def __init__(self, rule, i, j):
    self.rule = rule
    self.i = i
    self.j = j
  def toString(self):
    s = ""
    s += self.rule.toString() + ": between " + self.rule.rhs[self.i] + \
      " and " + self.rule.rhs[self.j]
    return s

class ReductionNode:
  def __init__(self, norule, rule = False):
    if rule:
      self.reducible = True
      self.rule = rule
    else:
      self.reducible = False
      self.rule = norule
    self.sons = dict()
  def hasSonWith(self, label):
    if label in self.sons:
      return self.sons[label]
    return False
  def getSize(self):
    size = 2
    for label in self.sons:
      son = self.sons[label]
      size += son.getSize()
      size += 2
    return size
  def toVector(self, vector, offset, nonterminals, terminals):
    sonsNumber = len(self.sons)
    sonsOffsets = dict()
    # Call sons and populate sonsOffsets.
    for label in self.sons:
      son = self.sons[label]
      vector,sonsOffsets[label],offset = son.toVector(vector, offset, nonterminals, terminals)
    myOffset = offset
    vector[myOffset] = self.rule
    vector[myOffset + 1] = sonsNumber*2
    offset += 2
    for label in self.sons:
      # Get label value.
      labelIndex =  bitPack.tokenToInt(label, nonterminals, terminals)
      vector[offset] = labelIndex
      vector[offset + 1] = sonsOffsets[label]
      offset += 2
    return vector, myOffset, offset
  def toString(self, level):
    s = ""
    s += str(self.rule) + "\n"
    for label in self.sons:
      son = self.sons[label]
      s += "  "*(level + 1) + label + ":"
      s += son.toString(level + 1)
    return s

